#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

struct wav_header
{
    char chunk_id[4];
    uint32_t chunk_size;
    char format[4];

    char subchunk1_id[4];
    uint32_t subchunk1_size;
    uint16_t audio_format;
    uint16_t num_channels;
    uint32_t sample_rate;
    uint32_t byte_rate;
    uint16_t block_align;
    uint16_t bits_per_sample;

    char subchunk2_id[4];
    uint32_t subchunk2_size;
};

//获取文件大小
//失败返回-1
long fsize(FILE* fp)
{
    //保存当前位置
    long pos = ftell(fp);
    if (pos < 0)
    {
        return -1;
    }
    //移动到文件尾
    if (fseek(fp, 0, SEEK_END) < 0)
    {
        return -1;
    }

    long size = ftell(fp);
    fseek(fp, pos, SEEK_SET);
    return size;
}

int main(int argc, char** argv)
{
    struct wav_header header;

    FILE* pcm = fopen(argv[1], "rb");
    if (!pcm)
    {
        perror("open pcm file error");
        return EXIT_FAILURE;
    }

    FILE* wav = fopen(argv[2], "wb");
    if (!wav)
    {
        perror("open wav file error");
        return EXIT_FAILURE;
    }

    //文件标识
    memcpy(header.chunk_id, "RIFF", sizeof(header.chunk_id));

    int size = (int)fsize(pcm);
    if (size < 0)
    {
        perror("get pcm file size error");
        return EXIT_FAILURE;
    }
    //文件大小
    header.chunk_size = size + sizeof(struct wav_header) - 8;
    //文件类型
    memcpy(header.format, "WAVE", sizeof(header.format));

    //格式块标识
    memcpy(header.subchunk1_id, "fmt ", sizeof(header.subchunk1_id));
    header.subchunk1_size = 16; //格式块长度
    header.audio_format = 1; // 编码格式PCM
    header.num_channels = 1; // 声道个数
    header.sample_rate = 16000; // 采样频率
    header.byte_rate = 32000; //数据传输速率 = 声道数×采样频率×每样本字节数
    header.block_align = 2;    //数据块对齐单位 = 采样帧大小 = 声道数×每样本字节数
    header.bits_per_sample = 16; //采样位数

    //数据块标识
    memcpy(header.subchunk2_id, "data", sizeof(header.subchunk2_id));
    //数据块大小
    header.subchunk2_size = size;

    //将wav文件头写入文件
    fwrite(&header, sizeof(header), 1, wav);

    uint16_t frame;
    while(fread(&frame, sizeof(frame), 1, pcm))
    {
        fwrite(&frame, sizeof(frame), 1, wav);
    }

    fclose(pcm);
    fclose(wav);

    return EXIT_SUCCESS;
}
